#####################################################################
# Product:      KnowledgeEngine (Plone Edition)
#
# File:         GenericObjectCatalogService.py
#
# Copyright:    Copyright (c) 2004, Faulkner Technologies
#
# Author:       Tom Cameron
#
# Description:  ZCatalog based service for cataloging all generic objects.
#
#
#####################################################################

#####################################################################
## KnowledgeEngine Library Imports
from Products.KnowledgeEngine.Common import *
from Products.KnowledgeEngine.Core import *
from Products.KnowledgeEngine.Service import ServiceInfo, Service

#####################################################################
## Zope Library Imports
from Products.CMFPlone.CatalogTool import CatalogTool
from Products.ZCatalog.ZCatalog import ZCatalog
from AccessControl import ClassSecurityInfo
from Acquisition import aq_base
from App.ImageFile import ImageFile

#####################################################################
## Python Library Imports
#(None)

#####################################################################
## GenericObjectCatalogServiceInfo Class Definition
class GenericObjectCatalogServiceInfo(ServiceInfo):
    """
        Defines the assessment storage service meta-information
    """

    #---------------------------------------------------------------#

    def getClassName(self):
        """
            Returns the name of the class for which
            we are providing information.
        """
        return 'GenericObjectCatalogService'

    #---------------------------------------------------------------#

    def getDisplayName(self):
        """
            Return a friendly name for the class instances
            (this is used for displaying in lists etc)
        """

        return "KnowledgeEngine: Generic Object Catalog Service"

    #---------------------------------------------------------------#

    def getServiceName(self):
        """
            Return the lookup-identity.

            This method must be overriden to provide a unique service name
            (this name is used to set the zope id of the service
            when created)
        """

        return "knowledgeengine_genericobjectcatalogservice"

#####################################################################
## GenericObjectCatalogService Class Definition
class GenericObjectCatalogService(CatalogTool, Service):
    """
        Defines a tool that may be used to catalog generic objects
    """

    #---------------------------------------------------------------#

    #ABSTRACT TRANSIENT: a ServiceInfo implementation instance to provide info about this service
    _SERVICEINFO = GenericObjectCatalogServiceInfo()

    #ZOPE: setup standard management tabs
    manage_options = CatalogTool.manage_options

    security = ClassSecurityInfo()

    id = 'knowledgeengine_genericobjectcatalogservice'

    meta_type = portal_type = 'KnowledgeEngine Catalog'

    #---------------------------------------------------------------#

    def __init__(self):
        """
            Constructor for the object
        """

        CatalogTool.__init__(self)

    #---------------------------------------------------------------#

    def searchResults(self, REQUEST=None, **kw):
        """
            While I want to base this catalog on the Plone Catalog
            I dont want the search results to check for permissions
            and workflow the way the plone catalog does so Im patching
            back the original ZCatalog searchResults Method.
        """

        return apply(ZCatalog.searchResults, (self, REQUEST), kw)

    #---------------------------------------------------------------#

    def manage_afterAdd(self, item, container):
        """ 
            Call all manage_afterAdd hooks
        """

        # Makes sure the SearchableText index is a ZCTextIndex
        if item is self and not hasattr(aq_base(self), 'genericobject_lexicon'):
            class args:
                def __init__(self, **kw):
                    self.__dict__.update(kw)

            self.manage_addProduct[ 'ZCTextIndex' ].manage_addLexicon(
                'genericobject_lexicon',
                elements=[
                args(group= 'Case Normalizer' , name= 'Case Normalizer' ),
                args(group= 'Stop Words' , name= " Don't remove stop words" ),
                args(group= 'Word Splitter' , name= "Unicode Whitespace splitter" ),
                ]
                )

            extra = args( doc_attr = 'SearchableText',
                          lexicon_id = 'genericobject_lexicon',
                          index_type  = 'Okapi BM25 Rank' )

            if 'SearchableText' in self.indexes():
                self.manage_delIndex(['SearchableText'])
            self.manage_addIndex('SearchableText', 'ZCTextIndex', extra=extra)

    #---------------------------------------------------------------#

    def enumerateIndexes( self ):
        """
            Return a list of ( index_name, type ) pairs for the initial
            index set.
            
            id is deprecated and may go away, use getId!
        """
        
        struct = ( ('id', 'FieldIndex')
               , ('getId', 'FieldIndex')
               , ('getIdentity', 'FieldIndex')
               , ('getModelIdentity', 'FieldIndex')
               , ('getTitle', 'TextIndex')
               , ('getDescription', 'TextIndex')
               , ('getReference', 'FieldIndex')
               , ('isPublishable', 'FieldIndex')
               , ('getOrder', 'FieldIndex')
               , ('getClassName', 'FieldIndex')
               , ('meta_type', 'FieldIndex')
               , ('portal_type', 'FieldIndex')
               , ('path', 'PathIndex')
               , ('getClassFamilyName', 'FieldIndex'),
               )        
        
        # HACKHACK - Jamesd 2006-05-08, Plone 2.1 support.
        # CMFCore 1.5 introduces a breaking change here- Tuples with three items instead of two.
        # Call the base class to check which version we are running, and alter the struct as needed
        
        peek = CatalogTool.enumerateIndexes(self)[0]
        if len(peek) == 2:
            # Base tuples have two elements, return as usual
            return struct
        
        elif len(peek) == 3:
            # Base tuples have three elements, must be running CMF 1.5+. Upgrade our structure and return    
            newstruct = ()
            for row in struct: 
                row += (None,)
                newstruct += (row,)
                
            return newstruct

    #---------------------------------------------------------------#

    security.declarePublic( 'enumerateColumns' )
    def enumerateColumns( self ):
        """
            Return a sequence of schema names to be cached.
            id is deprecated and may go away, use getId!
        """
        
        return ( 'id'
               , 'getId'
               , 'getIdentity'
               , 'getTitle'
               , 'getDescription'
               , 'getReference'
               , 'getReportTitle'
               , 'isPublishable'
               , 'getOrder'
               , 'getClassName'
               , 'getModelIdentity'
               , 'getClassFamilyName'               
               )
    #---------------------------------------------------------------#

#####################################################################
## Class Initialisation
# (none)

# Register Service Information with the Knowledge Engine
registerServiceClass(GenericObjectCatalogService)

#####################################################################
